/* SpotterApp.m - The main UIApplication of iSpotter.
 *
 * Copyright (C) 2008 Yuuichi Teranishi
 *
 * This file is derived from Stumbler, a program developed by iphone-wireless
 * project.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * published by the Free Software Foundation.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; If not, write to the Free Software Foundation,
 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
#import <CoreFoundation/CoreFoundation.h>
#import <Foundation/Foundation.h>
#import <UIKit/CDStructures.h>
#import <UIKit/UIHardware.h>
#import <UIKit/UIView.h>
#import <UIKit/UIWindow.h>
#import <UIKit/UITextView.h>
#import <UIKit/UINavigationBar.h>
#import <UIKit/UINavigationItem.h>

#import <GraphicsServices/GraphicsServices.h>

#include <stdio.h>
#include <sys/stat.h>

#import "LockyDB.h"
#import "SpotterApp.h"

static SpotterApp *sharedInstance;

@implementation SpotterApp

+ (SpotterApp *)sharedInstance
{
  if (!sharedInstance)
    sharedInstance = [[SpotterApp alloc] init];
        
  return sharedInstance;
}

- (void) applicationSuspend:(GSEvent *) event {
}


- (void)setServer:(SimpleHTTPServer *)sv
{
    [server autorelease];
    server = [sv retain];
}

- (void)showMapLat:(double)y lng:(double)x
{
  NSURL *baseurl = [[NSURL alloc]
		     initWithString:
		       [@"maps:q="
			 stringByAppendingFormat:
			   @"%f,%f", y, x]];
  [self openURL:baseurl];
}

- (void)stopProcessing
{
  // nothing to do;
}

- (void)prepare
{
  struct stat s;

  if (stat("/var/mobile/iSpotter", &s) < 0) {
    if (mkdir("/var/mobile/iSpotter", S_IRWXU) < 0) {
      NSLog(@"cannot create /var/mobile/iSpotter");
      exit(1);
    }
  }

  if (stat("/var/mobile/iSpotter/cache", &s) < 0) {
    if (mkdir("/var/mobile/iSpotter/cache", S_IRWXU) < 0) {
      NSLog(@"cannot create /var/mobile/iSpotter/cache");
      exit(1);
    }
  }

  // 1.0.1 or older
  if (!(stat("/var/mobile/Library/Preferences/locky.db", &s) < 0)
      && stat("/var/mobile/iSpotter/locky.db", &s) < 0) {
    if (rename("/var/mobile/Library/Preferences/locky.db",
	       "/var/mobile/iSpotter/locky.db") < 0) {
      NSLog(@"cannot rename /var/mobile/iSpotter/locky.db");
      // ignore error
    }
  }
  if (!(stat("/var/mobile/Library/Preferences/spotter_movelog.db", &s) < 0)
      && stat("/var/mobile/iSpotter/spotter_movelog.db", &s) < 0) {
    if (rename("/var/mobile/Library/Preferences/spotter_movelog.db",
	       "/var/mobile/iSpotter/spotter_movelog.db") < 0) {
      NSLog(@"cannot rename /var/mobile/iSpotter/spotter_movelog.db");
      // ignore error
    }
  }

  if (stat("/Applications/iSpotter.app/Search.png", &s) < 0) {
    // Detect
    symlink("/Applications/YouTube.app/Search.png",
	    "/Applications/iSpotter.app/Search.png");
    symlink("/Applications/YouTube.app/SearchSelected.png",
	    "/Applications/iSpotter.app/SearchSelected.png");
    // History
    symlink("/Applications/YouTube.app/History.png",
	    "/Applications/iSpotter.app/History.png");
    symlink("/Applications/YouTube.app/HistorySelected.png",
	    "/Applications/iSpotter.app/HistorySelected.png");    
    // Learn
    symlink("/Applications/YouTube.app/MostRecent.png",
	    "/Applications/iSpotter.app/MostRecent.png");
    symlink("/Applications/YouTube.app/MostRecentSelected.png",
	    "/Applications/iSpotter.app/MostRecentSelected.png");
    // Web
    symlink("/Applications/YouTube.app/TopRated.png",
	    "/Applications/iSpotter.app/TopRated.png");
    symlink("/Applications/YouTube.app/TopRatedSelected.png",
	    "/Applications/iSpotter.app/TopRatedSelected.png");
  }
}

- (void)replyStringOnMainThread:(NSString *)body {
  [server replyWithData:[body dataUsingEncoding:NSUTF8StringEncoding]
	  MIMEType:@"text/plain"];
}

- (void)replyString:(NSString *)body {
  [ self performSelectorOnMainThread: @selector(replyStringOnMainThread:)
	 withObject: body waitUntilDone:YES ];  
}

- (void)alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
  if (button == 1) {
    [mainView addSite: alertSite permission:YES];
    [mainView scanWithReplyDelegate: self];
  }
  else if (button == 2) {
    [mainView scanWithReplyDelegate: self];
  }
  else {
    [mainView addSite: alertSite permission:NO];
    NSString *errorMsg = @"Your request is not allowed";
    [server replyWithStatusCode:400 // Bad Request
	    message:errorMsg];
  }
  [sheet dismiss];
}

- (void) doDetectLocation:(NSDictionary *)request {
  if ([request objectForKey:@"referer"] == nil &&
      [[[request objectForKey:@"connection"] address] isEqualToString:@"127.0.0.1"]
      ) {
    // local direct access; granted.
    [mainView scan];
    // reply with no data.
    [server replyWithStatusCode:200 message:@""];
  }
  else {
    if ([request objectForKey:@"referer"] == nil && !preferences.direct) {
      NSString *errorMsg = @"Your request is not allowed";
      [server replyWithStatusCode:400 // Bad Request
	      message:errorMsg];
    }
    else {
      NSString *site = ([request objectForKey:@"referer"] == nil) ?
	[[request objectForKey:@"connection"] address] : [request objectForKey:@"referer"];
      int permission = [mainView permissionForSite: site];
      if (permission == 1) {
	[mainView scanWithReplyDelegate: self];
      }
      else if (permission == 2) {
	[server replyWithStatusCode:200
		message:@"recvLoc(0,0,-4,{})"];	  // Denied
      }
      else { // undefined, ask.
	UIAlertSheet *alertSheet = [ [ UIAlertSheet alloc ] 
				     initWithFrame:
				       CGRectMake(0, 240, 320, 240)];
	alertSite = site;
	[ alertSheet setTitle:@"iSpotter Detection Request" ];
	[ alertSheet setBodyText:
		       [@"Do you allow to notify your current location to "
			 stringByAppendingFormat: @"%@ ?",
			 [request objectForKey:@"referer"] == nil ? [@"direct access from " stringByAppendingString: [[request objectForKey:@"connection"] address]] : [request objectForKey:@"referer"]]];
	[ alertSheet addButtonWithTitle:@"Allow for this site" ];
	[ alertSheet addButtonWithTitle:@"Allow for current request" ];
	[ alertSheet setDestructiveButton: [ alertSheet addButtonWithTitle:@"Never for this site" ]];
	[ alertSheet setDelegate: self ];
	[ alertSheet setShowsOverSpringBoardAlerts:YES];
	//[ alertSheet popupAlertAnimated:YES];
	//[ alertSheet presentSheetFromAboveView:self];
	[ alertSheet presentSheetInView: mainView];
      }
    }
  }
}

- (void)processURL:(NSDictionary *)request
{
  NSURL *path = [request objectForKey:@"url"];
  NSString *urlString = [@"http:/" stringByAppendingString:[path absoluteString]];
  NSArray *params = [[path query] componentsSeparatedByString:@"&"];
  int i;
  NSMutableDictionary *pairs = [[NSMutableDictionary alloc] init];
  for (i = 0; i < [params count]; i++) {
    NSArray *pair = [[params objectAtIndex: i] componentsSeparatedByString:@"="];
    [pairs setObject: [pair objectAtIndex: 1] forKey: [pair objectAtIndex: 0]];
  }
  //  NSURL *url = [NSURL URLWithString:urlString];

  // PlaceEngine compatibility
  if (preferences.pengine && [[path path] isEqualToString: @"/rtagjs"]) {
    [self doDetectLocation: request];
  }
  else if (preferences.pengine && [[path path] isEqualToString: @"/ackjs"]) {
    // Pretend PlaceEngine
    [server replyWithStatusCode:200 message: @"ackRTAG('o080131')"];
  }
  else if ([[pairs objectForKey:@"c"] isEqualToString:@"detect"]) {
    [self doDetectLocation: request];
  }
  else if ([[pairs objectForKey:@"c"] isEqualToString:@"logs"]) {
    [ mainView redrawTrails: [pairs objectForKey:@"date"] ];
    [server replyWithStatusCode:200 message: @""]; // NULL result;
  }
  else {
    [server replyWithStatusCode:404 // Not Found
	    message: @"The document is not found"];
  }
}

- (UIWindow *) getWindow
{
  return window;
}

- (void)applicationDidFinishLaunching: (id)unused
{
  [self prepare];

  [self _setSuspendedUnderLock:NO];
  sharedInstance = self;
  // screen rect
  CGRect screenRect = [UIHardware fullScreenApplicationContentRect];
	
  // frame rect
  CGRect frame;
  frame.origin = CGPointZero;
  frame.size = screenRect.size;
	
  // navigationbar size
  CGSize navBarSize = [UINavigationBar defaultSize];
  
  // create window
  window = [[UIWindow alloc] initWithContentRect: screenRect];

  logdb = [[LogDB alloc] initWithFile: @"/var/mobile/iSpotter/spotter_movelog.db"];
  [logdb setAlertDelegate: self];

  [self setServer:[[[SimpleHTTPServer alloc] initWithTCPPort:5448
					     delegate:self]
		    autorelease]];

  // create main view
  mainView = [[MainView alloc] initWithFrame: frame delegate: self logDB: logdb];

  [mainView setMapLauncher: self];

  // show window
  [window orderFront: self];
  [window makeKey: self];
  [window _setHidden: NO];
  
  // set content view
  [window setContentView: mainView];

  [mainView start];

}

-(void)showProgress:(NSString *)label
{
  progress = [[UIProgressHUD alloc] initWithWindow: window];
  [progress setText: label];
  [progress drawRect: CGRectMake(0.0f, 0.0f, 10.0f, 10.0f)];
  [progress show: YES];
  [mainView addSubview:progress];
}

- (void)hideProgress
{
  [progress show: NO];
  [progress removeFromSuperview];
}

@end
